﻿using Abp.Authorization;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Application.AccessStatistics.Dto;
using Mt.Site.Core.AccessStatistics.Permissions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;


namespace Mt.Site.Application.AccessStatistics
{
    partial class VisitStatisticAppService
    {
        [AbpAuthorize(ASPermissions.Pages_Manage_AccessStatistics_Query)]
        public async Task<PagesAnalysisOut> GetPagesAnalysisAsync(PagesAnalysisInput input)
        {
            var startTime = input.StartTime;
            var endTime = input.EndTime;
            
            if (!_visitStatisticHelper.CheckTimeFormat(ref startTime, ref endTime))
            {
                return null;
            }
            var TenancyName = GetCurrentTenant().TenancyName;
            var PagesAnalysisDto = new PagesAnalysisOut();
            input.StartTime = startTime;
            input.EndTime = endTime;
            PagesAnalysisDto.StartTime = startTime.ToString("yyyy-MM-dd");
            PagesAnalysisDto.EndTime = endTime.ToString("yyyy-MM-dd");
            PagesAnalysisDto.AvgVisitTime = "00:00:00";
            PagesAnalysisDto.IpNum = 0;
            PagesAnalysisDto.NewNum = 0;
            PagesAnalysisDto.OutRate = 0;
            PagesAnalysisDto.PvNum = 0;
            PagesAnalysisDto.UvNum = 0;
            var outNumber = 0;
            var lengthOfStay = 0;

            var ipQuery = from dataTwo in
                              from data in _AccessDataRespository.GetAll()
                              .PagesAnalysisQuery(input, TenancyName)
                              group data by new { Ip = data.ClientIp, Url = data.Url } into t
                              select new
                              {
                                  Ip = t.Key.Ip,
                                  Url = t.Key.Url
                              }
                          group dataTwo by new { Url = dataTwo.Url } into tTwo
                          select new
                          {
                              IpNum = tTwo.Count(item => item.Ip != null && item.Ip != ""),
                              Url = tTwo.Key.Url
                          };

            var query = from dataTwo in
                            from data in _AccessDataRespository.GetAll()
                            .PagesAnalysisQuery(input, TenancyName)
                            group data by new { Url = data.Url, Accout = data.Acount } into t
                            select new
                            {
                                Account = t.Key.Accout,
                                Url = t.Key.Url,
                                PvNum = t.Count(),
                                OutNum = t.Sum(item => item.IsBounced),
                                NewNum = t.Sum(item => item.IsNewVisitor),
                                LengthOfStay = t.Sum(item => item.LengthOfStay)
                            }
                        group dataTwo by new { Url = dataTwo.Url } into tTwo
                        select new
                        {
                            UvNum = tTwo.Count(item => item.Account != null && item.Account != ""),
                            PvNum = tTwo.Sum(item => item.PvNum),
                            NewNum = tTwo.Sum(item => item.NewNum),
                            OutNum = tTwo.Sum(item => item.OutNum),
                            LengthOfStay = tTwo.Sum(item => item.LengthOfStay),
                            Url = tTwo.Key.Url
                        };

            var ipList = await ipQuery.ToListAsync();
            var list = await query.ToListAsync();

            var PageDetailItems = new List<PagesDetailItem>();
            foreach (var item in list)
            {
                var pagesDetailItem = new PagesDetailItem();
                pagesDetailItem.VisitUrl = item.Url;
                pagesDetailItem.UvNum = item.UvNum;
                pagesDetailItem.PvNum = item.PvNum;
                pagesDetailItem.NewNum = item.NewNum;
                pagesDetailItem.LengthOfStay = item.LengthOfStay;
                pagesDetailItem.OutRate = _visitStatisticHelper.BounceRateCalc(item.OutNum, item.PvNum);
                pagesDetailItem.AvgVisitTime = _visitStatisticHelper.NumberToTime(item.LengthOfStay, item.PvNum, item.OutNum);

                PagesAnalysisDto.UvNum += item.UvNum;
                PagesAnalysisDto.PvNum += item.PvNum;
                PagesAnalysisDto.NewNum += item.NewNum;
                lengthOfStay += item.LengthOfStay;
                outNumber += item.OutNum;

                foreach (var p in ipList)
                {
                    if (item.Url == p.Url)
                    {
                        pagesDetailItem.IpNum = p.IpNum;
                        PagesAnalysisDto.IpNum += p.IpNum;
                    }
                }
                PageDetailItems.Add(pagesDetailItem);
            }


            PagesAnalysisDto.OutRate = _visitStatisticHelper.BounceRateCalc(outNumber, PagesAnalysisDto.PvNum);
            PagesAnalysisDto.AvgVisitTime = _visitStatisticHelper.NumberToTime(lengthOfStay, PagesAnalysisDto.PvNum, outNumber);
            PagesAnalysisDto.PagesDetailItems = PageDetailItems;
            return PagesAnalysisDto;
        }

        [AbpAuthorize(ASPermissions.Pages_Manage_AccessStatistics_Query)]
        public async Task<PageMenuAnalysisOut> GetPagesMenuAnalysisAsync(PageMenuAnalysisInput input)
        {
            var startTime = input.StartTime;
            var endTime = input.EndTime;
            if (!_visitStatisticHelper.CheckTimeFormat(ref startTime, ref endTime))
            {
                return null;
            }
            var TenancyName = GetCurrentTenant().TenancyName;
            var PageMenuAnalysisDto = new PageMenuAnalysisOut();
            input.StartTime = startTime;
            input.EndTime = endTime;
            PageMenuAnalysisDto.StartTime = startTime.ToString("yyyy-MM-dd");
            PageMenuAnalysisDto.EndTime = endTime.ToString("yyyy-MM-dd");
            PageMenuAnalysisDto.AvgVisitTime = "00:00:00";
            PageMenuAnalysisDto.IpNum = 0;
            PageMenuAnalysisDto.NewNum = 0;
            PageMenuAnalysisDto.OutRate = 0;
            PageMenuAnalysisDto.PvNum = 0;
            PageMenuAnalysisDto.UvNum = 0;
            var outNumber = 0;
            var lengthOfStay = 0;

            var ipQuery = from dataTwo in
                              from data in _AccessDataRespository.GetAll()
                              .PagesMenuAnalysisQuery(input, TenancyName)
                              group data by new { Ip = data.ClientIp, MenuId = data.MenuId } into t
                              select new
                              {
                                  Ip = t.Key.Ip,
                                  MenuId = t.Key.MenuId
                              }
                          group dataTwo by new { MenuId = dataTwo.MenuId } into tTwo
                          select new
                          {
                              IpNum = tTwo.Count(item => item.Ip != null && item.Ip != ""),
                              MenuId = tTwo.Key.MenuId
                          };

            var query = from dataTwo in
                            from data in _AccessDataRespository.GetAll()
                            .PagesMenuAnalysisQuery(input, TenancyName)
                            group data by new { MenuId = data.MenuId, Accout = data.Acount } into t
                            select new
                            {
                                Account = t.Key.Accout,
                                MenuId = t.Key.MenuId,
                                PvNum = t.Count(),
                                OutNum = t.Sum(item => item.IsBounced),
                                NewNum = t.Sum(item => item.IsNewVisitor),
                                LengthOfStay = t.Sum(item => item.LengthOfStay)
                            }
                        group dataTwo by new { MenuId = dataTwo.MenuId } into tTwo
                        select new
                        {
                            UvNum = tTwo.Count(item => item.Account != null && item.Account != ""),
                            PvNum = tTwo.Sum(item => item.PvNum),
                            NewNum = tTwo.Sum(item => item.NewNum),
                            OutNum = tTwo.Sum(item => item.OutNum),
                            LengthOfStay = tTwo.Sum(item => item.LengthOfStay),
                            MenuId = tTwo.Key.MenuId
                        };

            var ipList = await ipQuery.ToListAsync();
            var list = await query.ToListAsync();

            var menuIds = new List<Guid>();
            ipList.ForEach(item =>
            {
                if (item.MenuId != null && item.MenuId != Guid.Empty)
                {
                    menuIds.Add(item.MenuId.Value);
                }
            });

            var menuList = await _MenuRepository.GetAllListAsync(item => menuIds.Contains(item.Id));

            var menuDetailItems = new List<MenuDetailItem>();
            foreach (var item in list)
            {
                var menuDetailItem = new MenuDetailItem();
                menuDetailItem.MenuId = item.MenuId.Value;
                menuDetailItem.UvNum = item.UvNum;
                menuDetailItem.PvNum = item.PvNum;
                menuDetailItem.NewNum = item.NewNum;
                menuDetailItem.LengthOfStay = item.LengthOfStay;
                menuDetailItem.OutRate = _visitStatisticHelper.BounceRateCalc(item.OutNum, item.PvNum);
                menuDetailItem.AvgVisitTime = _visitStatisticHelper.NumberToTime(item.LengthOfStay, item.PvNum, item.OutNum);

                PageMenuAnalysisDto.UvNum += item.UvNum;
                PageMenuAnalysisDto.PvNum += item.PvNum;
                PageMenuAnalysisDto.NewNum += item.NewNum;
                lengthOfStay += item.LengthOfStay;
                outNumber += item.OutNum;

                foreach (var p in ipList)
                {
                    if (item.MenuId == p.MenuId)
                    {
                        menuDetailItem.IpNum = p.IpNum;
                        PageMenuAnalysisDto.IpNum += p.IpNum;
                    }
                }
                foreach (var m in menuList)
                {
                    if (item.MenuId == m.Id)
                    {
                        menuDetailItem.MenuName = m.DisplayName;
                    }
                }
                menuDetailItems.Add(menuDetailItem);
            }


            PageMenuAnalysisDto.OutRate = _visitStatisticHelper.BounceRateCalc(outNumber, PageMenuAnalysisDto.PvNum);
            PageMenuAnalysisDto.AvgVisitTime = _visitStatisticHelper.NumberToTime(lengthOfStay, PageMenuAnalysisDto.PvNum, outNumber);
            PageMenuAnalysisDto.MenuDetailItems = menuDetailItems;
            return PageMenuAnalysisDto;
        }

    }


}
